/*
 * Trade.cpp
 *
 *  Created on: 2013. 10. 15.
 *      Author: mega@gamevil.com
 */

#include "../User.h"
#include "Trade.h"
#include "Static.h"

namespace ProjectZ { namespace NLogic {

Trade::Trade(User * pUser)
{
	_user = pUser;
	_bSoldItemLoad = false;
	_bLoad			= false;
}

Trade::~Trade()
{
	std::for_each(clsTradeItemTree.begin(), clsTradeItemTree.end(), [](REGISTITEMTREE::value_type& v) {
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL( v.second );
	} );
}

void
Trade::Initialize()
{
	_bLoad			= false;
}

void
Trade::Finalize()
{
	std::for_each(clsTradeItemTree.begin(), clsTradeItemTree.end(), [](REGISTITEMTREE::value_type& v) {
		NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL( v.second );
	} );
	clsTradeItemTree.clear();
}

bool
Trade::AddTradeItemData(NLogic::Trade::TradeItem * pTradeItem)
{
	if (NULL == pTradeItem)
		return false;

	NLogic::Trade::Key clsKey;
	clsKey.tradeSeq = pTradeItem->GetTradeSeq();
	clsKey.classType = pTradeItem->GetData().item.class_type;
	clsKey.sheetType = pTradeItem->GetData().item.sub_type;

	auto iter = clsTradeItemTree.find(clsKey);
	if (iter == clsTradeItemTree.end())
		clsTradeItemTree[clsKey] = pTradeItem;

	return true;
}

void
Trade::RemoveTradeItemData(NLogic::Trade::Key & clsKey)
{
	auto iter = clsTradeItemTree.find(clsKey);
	if (iter == clsTradeItemTree.end())
		return;

	NLogic::Trade::TradeItem * pTradeItem = iter->second;

	clsTradeItemTree.erase(iter);

	NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->DEL(pTradeItem);
}

NLogic::Trade::TradeItem *
Trade::GetTradeItemData(NLogic::Trade::Key & clsKey)
{
	auto iter = clsTradeItemTree.find(clsKey);
	if (iter == clsTradeItemTree.end())
		return NULL;

	return iter->second;
}

bool
Trade::IsExistTradeItemData(NLogic::Trade::Key & clsKey)
{
	auto iter = clsTradeItemTree.find(clsKey);
	if (iter == clsTradeItemTree.end())
		return false;

	return true;
}

void
Trade::TradeItemLoadToDatabase()
{
	if (true == _bLoad)
	{
		return;
	}

	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::SELECT);
	clsAuto->MakeQuery("SELECT * FROM PZ_TRADE_DATA_SELF_%d WHERE sell_user_seq=%d AND status = 0",
			_user->GetUserSeq() % 10,
			_user->GetUserSeq());

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_SLAVE), clsAuto))
	{
		DEBUGLOG("%s : false == ::Database::GETSESSION()->SyncExecute()", __FUNCTION__);
		return;
	}

	if (clsAuto->GetErrorIdx() != 0)
	{
		DEBUGLOG("%s : clsAuto->GetErrorIdx() != 0", __FUNCTION__);
		return;
	}

	while (clsAuto->Next())
	{
		uint64_t tradeSelfSeq;
		uint64_t tradeSeq;

		NLogic::Trade::TradeItem::Data clsData;

		clsAuto->GetRecord() >> tradeSelfSeq;
		clsAuto->GetRecord() >> tradeSeq;
		clsAuto->GetRecord() >> clsData.reg_user_seq;
		clsAuto->GetRecord() >> clsData.reg_slot_seq;
		clsAuto->GetRecord() >> clsData.buyer_slot_seq;
		clsAuto->GetRecord() >> clsData.item_price;
		clsAuto->GetRecord() >> clsData.reg_user_nickname;
		clsAuto->GetRecord() >> clsData.status;
		clsAuto->GetRecord() >> clsData.sell_info_visible;

		clsAuto->GetRecord() >> clsData.item.bag_type;
		clsAuto->GetRecord() >> clsData.item.bag_slot_number;
		clsAuto->GetRecord() >> clsData.item.quantity;
		clsAuto->GetRecord() >> clsData.item.class_type;
		clsAuto->GetRecord() >> clsData.item.sub_type;
		clsAuto->GetRecord() >> clsData.item.tid;
		clsAuto->GetRecord() >> clsData.item.iconidx;
		clsAuto->GetRecord() >> clsData.item.item_type;
		clsAuto->GetRecord() >> clsData.item.cur_duration;
		clsAuto->GetRecord() >> clsData.item.max_duration;
		clsAuto->GetRecord() >> clsData.item.set_type;
		clsAuto->GetRecord() >> clsData.item.non_identity;
		clsAuto->GetRecord() >> clsData.item.cur_refine_step;
		clsAuto->GetRecord() >> clsData.item.quality;
		clsAuto->GetRecord() >> clsData.item.level;

		for (int i = 0; i < 7; ++i)
		{
			clsAuto->GetRecord() >> clsData.item.eff_type[i];
			clsAuto->GetRecord() >> clsData.item.eff_pos[i];
			clsAuto->GetRecord() >> clsData.item.eff_value[i];
		}

		clsAuto->GetRecord() >> clsData.item.open_upgrade_stone_slot;
		clsAuto->GetRecord() >> clsData.item.ability_enhance_rate;
		clsAuto->GetRecord() >> clsData.item.max_enhance_step;
		clsAuto->GetRecord() >> clsData.item.buy_use;
		clsAuto->GetRecord() >> clsData.item.evolve_step;
		clsAuto->GetRecord() >> clsData.item.evolve_max;
		clsAuto->GetRecord() >> clsData.item.evolve_point;
		clsAuto->GetRecord() >> clsData.item.evolve_percent;
		clsAuto->GetRecord() >> clsData.item.evolve_value;

		clsAuto->GetRecord() >> clsData.reg_date;
		clsAuto->GetRecord() >> clsData.limit_date;
		clsAuto->GetRecord() >> clsData.sold_date;

		NLogic::Trade::TradeItem * pTradeItem = NLogic::Static::InstancePtr()->GETTRADEITEMPOOL()->NEW();
		pTradeItem->Open_FromDatabase(tradeSeq, tradeSelfSeq, clsData, _user);
		this->AddTradeItemData(pTradeItem);
	}

	_bLoad = true;
}

bool
Trade::SoldItemLoadToDatabase()
{
	if (true == _bSoldItemLoad)
		return true;

	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::SELECT);
	clsAuto->MakeQuery("SELECT seq, class_type, sub_type, tid, cur_refine_step, quality, sell_price, sold_date FROM PZ_TRADE_DATA_SELF_%d WHERE sell_user_seq=%d AND status = 1 AND sell_info_visible = 0",
			_user->GetUserSeq() % 10,
			_user->GetUserSeq());

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_SLAVE), clsAuto))
	{
		DEBUGLOG("%s : false == ::Database::GETSESSION()->SyncExecute()", __FUNCTION__);
		return false;
	}

	if (clsAuto->GetErrorIdx() != 0)
	{
		DEBUGLOG("%s : clsAuto->GetErrorIdx() != 0", __FUNCTION__);
		return false;
	}

	while (clsAuto->Next())
	{
		NLogic::Trade::SoldItem stSoldItem;

		clsAuto->GetRecord() >> stSoldItem.seq;
		clsAuto->GetRecord() >> stSoldItem.classType;
		clsAuto->GetRecord() >> stSoldItem.sheetType;
		clsAuto->GetRecord() >> stSoldItem.tid;
		clsAuto->GetRecord() >> stSoldItem.curRefineStep;
		clsAuto->GetRecord() >> stSoldItem.itemQuality;
		clsAuto->GetRecord() >> stSoldItem.itemPrice;
		clsAuto->GetRecord() >> stSoldItem.soldTime;

		clsSoldItemVector.push_back(stSoldItem);
	}

	_bSoldItemLoad = true;

	return true;
}

bool
Trade::UpdateDatabaseSoldItemShowStatus(uint64_t seq)
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_update_trade_item_soldout_info_visible(%lld,%d)", seq, _user->GetUserSeq() % 10);

	DEBUGLOG("%s : %s", __FUNCTION__, clsAuto->GetQueryString());

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_MASTER), clsAuto))
	{
		DEBUGLOG("%s : false == ::Database::GETSESSION()->SyncExecute()", __FUNCTION__);
		return false;
	}

	if (clsAuto->GetErrorIdx() != 0)
	{
		DEBUGLOG("%s : clsAuto->GetErrorIdx() != 0", __FUNCTION__);
		return false;
	}

	return true;
}




void
Trade::TradeItem::Open_FromDatabase(uint64_t tradeSeq, uint64_t tradeSelfSeq, Data & data, User * pUser)
{
	_data			= data;
	_user			= pUser;
	_tradeSeq		= tradeSeq;
	_tradeSelfSeq	= tradeSelfSeq;
}

void
Trade::TradeItem::Open_Normal(uint64_t tradeSeq, Data & data, User * pUser)
{
	_data			= data;
	_user			= pUser;
	_tradeSeq		= tradeSeq;
}

void
Trade::TradeItem::WriteToItemPacket(::Network::Packet * pPacket)
{
	pPacket->MsgCat("%c", _data.item.cur_duration);
	pPacket->MsgCat("%c", _data.item.max_duration);
	pPacket->MsgCat("%c", _data.item.quantity);
	pPacket->MsgCat("%c", _data.item.set_type);
	pPacket->MsgCat("%c", _data.item.non_identity);
	pPacket->MsgCat("%c", _data.item.cur_refine_step);

	pPacket->MsgCat("%c", _data.item.quality);
	pPacket->MsgCat("%c", _data.item.level);

	for( int i=0 ; i<7 ; i++ )
	{
		pPacket->MsgCat("%c", _data.item.eff_type[i]);
		pPacket->MsgCat("%c", _data.item.eff_pos[i]);
		pPacket->MsgCat("%2d", _data.item.eff_value[i]);
	}

	pPacket->MsgCat("%c", _data.item.open_upgrade_stone_slot);
	pPacket->MsgCat("%c", _data.item.ability_enhance_rate);
	pPacket->MsgCat("%c", _data.item.max_enhance_step);
	pPacket->MsgCat("%c", _data.item.buy_use);

	pPacket->MsgCat("%c", _data.item.evolve_step);
	pPacket->MsgCat("%c", _data.item.evolve_max);
	pPacket->MsgCat("%2d", _data.item.evolve_point);
	pPacket->MsgCat("%2d", _data.item.evolve_percent);
	pPacket->MsgCat("%2d", _data.item.evolve_value);
	pPacket->MsgCat("%c", _data.item.class_type);
	pPacket->MsgCat("%c", _data.item.sub_type);
	pPacket->MsgCat("%2d", _data.item.tid);
}

bool
Trade::TradeItem::UpdateDatabaseCancelStatus()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_update_trade_item_status_cancel(%lld,%lld,%d,%d,%d)",
			_tradeSeq,
			_tradeSelfSeq,
			_data.item.class_type,
			_data.item.sub_type,
			_user->GetUserSeq() % 10);

	DEBUGLOG("%s : %s", __FUNCTION__, clsAuto->GetQueryString());

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_MASTER), clsAuto))
		return false;

	if (clsAuto->GetErrorIdx() != 0)
		return false;

	 _data.status = 2;

	return true;
}

bool
Trade::TradeItem::UpdateDatabaseSoldoutStatus()
{
	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::S_PROCEDURE);
	clsAuto->MakeQuery("call sp_update_trade_item_status_soldout(%lld,%d,%d,%d,%d)",
			_tradeSeq,
			_data.item.class_type,
			_data.item.sub_type,
			_data.buyer_slot_seq,
			_data.reg_user_seq % 10);

	DEBUGLOG("%s : %s", __FUNCTION__, clsAuto->GetQueryString());

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_MASTER), clsAuto))
		return false;

	if( clsAuto->GetErrorIdx() != 0 )
		return false;

	 _data.status = 1;

	return true;
}

int
Trade::TradeItem::SelectDatabaseTradeItemStatus()
{
//	int classType = _data.item.class_type;
//
//	if (-1 == classType)
//		classType = 99;

	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::SELECT);
//	clsAuto->MakeQuery("SELECT status FROM PZ_TRADE_DATA_%d_%d WHERE seq = %lld", _data.item.sub_type, classType, _tradeSeq);
	clsAuto->MakeQuery("SELECT status FROM PZ_TRADE_DATA_SELF_%d WHERE seq = %lld", _user->GetUserSeq() % 10, _tradeSelfSeq);

	DEBUGLOG("CS_MARKET_MY_ITEM_CANCEL : userseq=%d, query[%s]", _user->GetUserSeq(), clsAuto->GetQueryString());

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_SLAVE), clsAuto))
		return -1;

	if (clsAuto->GetErrorIdx() != 0)
		return -1;

	int itemStatus = 0;

	while (clsAuto->Next())
	{
		clsAuto->GetRecord() >> itemStatus;
	}

	return itemStatus;
}

bool
Trade::TradeItem::SelectDatabaseTradeItemDetailInfo()
{
	int classType = _data.item.class_type;

	if (-1 == classType)
		classType = 99;

	::Database::Command::Auto clsAuto(::Database::GETCOMMANDPOOL());
	clsAuto->SetQueryType(::Database::Command::SELECT);
	clsAuto->MakeQuery("SELECT * FROM PZ_TRADE_DATA_%d_%d WHERE seq = %lld", _data.item.sub_type, classType, _tradeSeq);

	if (false == ::Database::GETSESSION()->SyncExecute(static_cast<int>(DatabaseType::TRADE_SLAVE), clsAuto))
	{
		DEBUGLOG("%s : false == ::Database::GETSESSION()->SyncExecute()", __FUNCTION__);
		return false;
	}

	if (clsAuto->GetErrorIdx() != 0)
	{
		DEBUGLOG("%s : clsAuto->GetErrorIdx() != 0", __FUNCTION__);
		return false;
	}

	while (clsAuto->Next())
	{
		clsAuto->GetRecord() >> _tradeSeq;
		clsAuto->GetRecord() >> _data.reg_user_seq;
		clsAuto->GetRecord() >> _data.reg_slot_seq;
		clsAuto->GetRecord() >> _data.buyer_slot_seq;
		clsAuto->GetRecord() >> _data.item_price;
		clsAuto->GetRecord() >> _data.reg_user_nickname;
		clsAuto->GetRecord() >> _data.status;

		clsAuto->GetRecord() >> _data.item.bag_type;
		clsAuto->GetRecord() >> _data.item.bag_slot_number;
		clsAuto->GetRecord() >> _data.item.quantity;
		clsAuto->GetRecord() >> _data.item.class_type;
		clsAuto->GetRecord() >> _data.item.sub_type;
		clsAuto->GetRecord() >> _data.item.tid;
		clsAuto->GetRecord() >> _data.item.iconidx;
		clsAuto->GetRecord() >> _data.item.item_type;
		clsAuto->GetRecord() >> _data.item.cur_duration;
		clsAuto->GetRecord() >> _data.item.max_duration;
		clsAuto->GetRecord() >> _data.item.set_type;
		clsAuto->GetRecord() >> _data.item.non_identity;
		clsAuto->GetRecord() >> _data.item.cur_refine_step;
		clsAuto->GetRecord() >> _data.item.quality;
		clsAuto->GetRecord() >> _data.item.level;

		for (int i = 0; i < 7; ++i)
		{
			clsAuto->GetRecord() >> _data.item.eff_type[i];
			clsAuto->GetRecord() >> _data.item.eff_pos[i];
			clsAuto->GetRecord() >> _data.item.eff_value[i];
		}

		clsAuto->GetRecord() >> _data.item.open_upgrade_stone_slot;
		clsAuto->GetRecord() >> _data.item.ability_enhance_rate;
		clsAuto->GetRecord() >> _data.item.max_enhance_step;
		clsAuto->GetRecord() >> _data.item.buy_use;
		clsAuto->GetRecord() >> _data.item.evolve_step;
		clsAuto->GetRecord() >> _data.item.evolve_max;
		clsAuto->GetRecord() >> _data.item.evolve_point;
		clsAuto->GetRecord() >> _data.item.evolve_percent;
		clsAuto->GetRecord() >> _data.item.evolve_value;

		clsAuto->GetRecord() >> _data.reg_date;
		clsAuto->GetRecord() >> _data.limit_date;
		clsAuto->GetRecord() >> _data.sold_date;
	}

	return true;
}



} /*NLogic*/ } /* namespace ProjectZ */
